package cn.schoolwow.quickdao.module.database.parent.flow.executor;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.entity.SqlLog;
import cn.schoolwow.quickdao.module.database.parent.domain.ResultSetConsumer;
import cn.schoolwow.quickdao.module.database.parent.flow.executor.common.*;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class ExecuteQueryConnectionFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(ExecuteQueryConnectionFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        flowContext.executeFlowList(new BeforeExecuteFlow());
        flowContext.startFlow(new RealtimePrintStatementCommonFlow())
                .putCurrentCompositeFlowData("sqlLogType", 0)
                .execute();
        executeQuery(flowContext);
    }

    @Override
    public String name() {
        return "执行查询语句";
    }

    private void executeQuery(FlowContext flowContext) throws Exception {
        String name = flowContext.checkData("name", String.class);
        String sql = flowContext.checkData("sql", String.class);
        String formatSQL = flowContext.checkData("formatSQL", String.class);
        ResultSetConsumer resultSetConsumer = flowContext.checkData("resultSetConsumer", ResultSetConsumer.class);
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);

        flowContext.putTemporaryData("startTime", System.currentTimeMillis());
        try (Connection connection = quickDAOConfig.databaseContext.dataSource.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ) {
            flowContext.startFlow(new SetPrepareStatementParameterFlow())
                    .putTemporaryData("preparedStatement", preparedStatement)
                    .execute();
            try (ResultSet resultSet = preparedStatement.executeQuery();) {
                flowContext.startFlow(new InsertSqlLogFlow())
                        .putTemporaryData("sqlLogType", 0)
                        .execute();
                SqlLog sqlLog = (SqlLog) flowContext.checkData("sqlLog");
                logger.debug("[查询]名称:{},耗时:{}ms,执行语句:{}", name, sqlLog.getConsumeTime(), formatSQL);

                String content = "[查询]名称:"+name+",耗时:"+sqlLog.getConsumeTime()+"ms,执行语句:"+formatSQL+"\r\n";
                flowContext.startFlow(new RecordStatementFlow())
                        .putCurrentCompositeFlowData("content", content)
                        .execute();
                resultSetConsumer.consumeResultSet(resultSet);
            }
        } catch (Exception e) {
            flowContext.startFlow(new InsertSqlLogFlow())
                    .next(new ExecuteFailFlow())
                    .putTemporaryData("exception", e)
                    .putTemporaryData("sqlLogType", 0)
                    .execute();
            throw e;
        }finally {
            flowContext.removeData("parameters");
        }
    }

}
